﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MapEditor
{
    public class Undo
    {
        #region singleton
        private static Undo singleton;
        public static Undo Singleton
        {
            get 
            { 
                if (singleton == null)
                    singleton = new Undo();
                return singleton;
            }
        }
        #endregion
        private class Action
        {
            public int x;
            public int y;
            public Module module;
            public Tile lastTile;
            public Tile newTile;

            public Action(Module module, int x, int y, Tile lastTile, Tile newTile)
            {
                this.module = module;
                this.x = x;
                this.y = y;
                this.lastTile = lastTile;
                this.newTile = newTile;
            }
        }

        Stack<Action> stackUndo;
        Stack<Action> stackRedo;

        public Undo()
        {
            stackUndo = new Stack<Action>();
            stackRedo = new Stack<Action>();
        }

        /// <summary>
        /// appellé lorsque l'ont clique sur annuler.
        /// </summary>
        public void undo()
        {
            if (stackUndo.Count != 0)
            {
                Action action = stackUndo.Pop();
                if (action.module != null) //s'assure que le module n'a pas était suprimé
                {
                    action.module.changeTileNoUndo(action.x, action.y, action.lastTile);
                    stackRedo.Push(action);
                }
            }
        }

        /// <summary>
        /// appellé lorsque l'ont clique sur rétablir.
        /// </summary>
        public void redo()
        {
            if (stackRedo.Count != 0)
            {
                Action action = stackRedo.Pop();
                if (action.module != null) //s'assure que le module n'a pas était suprimé
                {
                    action.module.changeTileNoUndo(action.x, action.y, action.newTile);
                    stackUndo.Push(action);
                }
            }
        }

        /// <summary>
        /// appellé chaque fois qu'un layer est modifié, ajoute l'action à la stack.
        /// </summary>
        /// <param name="layer">module modifié</param>
        /// <param name="x"> position X de la tile modifié</param>
        /// <param name="y"> position Y de la tile modifié</param>
        /// <param name="lastId"> tile avant la modification</param>
        /// <param name="newId">tile aprés la modification</param>
        internal void newAction(Module module, int x, int y, Tile lastTile, Tile newTile)
        {
            stackRedo.Clear();
            stackUndo.Push(new Action(module, x, y, lastTile, newTile));
        }
    }
}
